<template>
  <div id="">
    <el-container id="question" class="text-32">
      <!-- <el-header>Header</el-header> -->
      <!-- <container> -->
      <el-aside ref="aside" :width="asidewidth" class="container-content">
        <el-scrollbar>
          <div class="container-content-item">
            <Questioncontext :question="question">
              <!-- <contextlist v-bind="{ question, isexample: !!match.isexample, }">
              </contextlist> -->
            </Questioncontext>
          </div>
        </el-scrollbar>
      </el-aside>
      <el-main class="position-relative p-0 container-right-box">
        <!-- 改变宽度的滑动条 -->
        <div class="zrleft" ref="zrleft"></div>
        <div class="monaco-container-box">
          <div ref="monacoEl" :style="{ height: monacoHeight }" class="monaco-container container-right">
            <div class="monaco-header">
              <div class="headers">
                <el-select size="default" :style="{ width: '106px', display: 'inline-block' }" v-model="language"
                  placeholder="请选择">
                  <el-option label="C" value="C">C</el-option>
                  <el-option label="C++" value="C++">C++</el-option>
                  <el-option label="Python" value="Python">Python</el-option>
                </el-select>
                <span v-if="['C++', 'C', 'CPP'].includes(language)">
                  &nbsp; <el-checkbox size="default" v-model="gccoptimize">O2优化</el-checkbox>
                </span>
                <span v-if="match.isfile">
                  &nbsp; <el-checkbox disabled size="default" v-model="match.isfile">文件读写</el-checkbox>
                </span>
                <el-text style="height: 32px;line-height: 32px;display: inline-block;"
                  :title="languages[language].title">
                  &nbsp; 编译环境：{{ languages[language].text }}
                </el-text>
              </div>
              <!-- <div>
                <el-button size="default" class="code-submit-btn" v-if="isMatch && match.format === 'IOI'"
                  type="primary" :loading="loading" @click="mySubmit(false)">
                  <el-icon>
                    <UploadFilled />
                  </el-icon>
                  &nbsp; 提交题目
                </el-button>
                <el-button size="default" v-else type="primary" :loading="loading" @click="mySubmit">
                  <el-icon>
                    <UploadFilled />
                  </el-icon>
                  &nbsp; 提交试卷
                </el-button>
              </div> -->
            </div>
            <!-- 编辑器 -->
            <MonaoEditor id="monaco" ref="editor" :value="context"
              v-bind="{ language, options: { minimap: { enabled: false, }, }, }" @change="change">
            </MonaoEditor>
          </div>
          <!-- 改变高度的滑动条 -->
          <div class="zrUp" v-if="!isCf" ref="zrUp"></div>
          <!-- 控制台 -->
          <ConsoleQuestion v-if="!isCf" class="console-question" :class="{ 'transition-enabled': isTransitionEnabled }"
            :style="{ height: consoleHeight }" ref="consoleQuestionRef" v-model:textarea="textarea"
            v-bind="{ ouput, drawer, runcode, range: question.range, loading: runTestLoading, question }">
          </ConsoleQuestion>
        </div>
      </el-main>
      <!-- </container> -->
    </el-container>
  </div>
</template>

<script setup lang='ts'>
import { useElementBounding, useMouse, useMousePressed } from "@vueuse/core";
import { ElMessage } from "element-plus";
import * as monaco from 'monaco-editor/esm/vs/editor/editor.api';
import { Socket } from "socket.io-client";
import { ComputedRef, computed, inject, nextTick, onMounted, onUnmounted, reactive, ref, toRaw, toRefs, watch, } from "vue";
import { useStore } from "vuex";
import { Apimatchuserquestion, jilurizhi } from "../../../api";
import MonaoEditor from "../../../components/MonaoEditor.vue";
import { Storekey } from "../../../interface";
import Studycodemodel from "../../../mysql_interface/studycodemodel";
import ConsoleQuestion from "../../components/watchQuestion/ConsoleQuestion.vue";
import { languages } from "../../data/data";
import Questioncontext from './context.vue';

type P = {
  question: Studycodemodel.Imatchquestion
  userdata: Record<string | number, any>
  setuserdata: Function
  index: number
  match: Studycodemodel.Iactivity
  matchuser?: Apimatchuserquestion,
  submit: Function,
  isMatch: boolean // 区分测评模式和比赛模式
}
const prop = defineProps<P>()
const { question, userdata, index, match, submit, isMatch } = toRefs(prop);
const gccoptimize = ref<boolean>(prop.match.iso2 || true)

const store = useStore(Storekey);

const drawer = ref(true);

const textarea = ref("");
const language = ref<keyof Studycodemodel.Ilang>('CPP');
const context = ref("");
const loading = ref(false);
// 运行测试 runTestLoading
const runTestLoading = ref(false);
const ouput = reactive({
  t: 0,
  stdout: "",
  stderr: "",
});

onMounted(() => {
  const app = document.querySelector("html");
  if (app) {
    app.style.overflowY = "hidden";
  }
  start();
  // 确保 zrUp 已初始化
  if (zrUp.value) {
    zrUp.value.addEventListener('mousedown', (event) => {
      // 记录鼠标点击时的偏移量
      initialMouseOffset = event.clientY - bottom.value
      console.log('mousedown', event.clientY, bottom.value, initialMouseOffset,)
    })
  }
});

onUnmounted(() => {
  document.title = "noipcode";
  prop.setuserdata(question.value.ID, {
    context: context.value,
    language: language.value,
    gccoptimize: gccoptimize.value,
  });
});

watch(
  () => question?.value.ID,
  (_v, ol) => {
    prop.setuserdata(ol, {
      context: context.value,
      language: language.value,
      gccoptimize: gccoptimize.value,
    });
    start();
  }
);

async function start() {
  nextTick(() => {
    const { name, ID } = toRaw(question.value);
    document.title = name || "noipcode";
    if (ID && userdata?.value) {
      context.value = userdata.value[ID]?.context;
      gccoptimize.value = userdata.value[ID]?.gccoptimize === undefined ? gccoptimize.value : userdata.value[ID]?.gccoptimize
      if (userdata.value[ID]?.language) {
        language.value = userdata.value[ID]?.language
      } else {
        language.value = prop.match.language || 'CPP'
      }
    } else {
      context.value = "";
    }
  });
}
const _runcode = inject("runcode", () => true);
const getuser = computed<Studycodemodel.Iuser>(() => {
  return store.getters.getuser;
});
const getcode = inject<
  ComputedRef<{
    data?: Studycodemodel.Iuserquestioninfo[];
    run?: true;
    error?: number;
    msg?: string;
  }>
>("getcode");

watch(
  () => getcode?.value,
  (d) => {
    if (d) {
      const { data, run, error, msg = "" } = d;
      if (error) {
        ElMessage.error("运行失败");
        ouput.stdout = "";
        ouput.t = NaN;
        ouput.stderr = msg;
      } else {
        ElMessage.success("运行成功");
        if (run && data) {
          Object.assign(ouput, data[0]);
        }
      }
      runTestLoading.value = false;
    }
  }
);

const consoleQuestionRef = ref()
watch(() => loading.value, (v) => {
  if (v && consoleQuestionRef.value) {
    consoleQuestionRef.value.consoleQuestionRef = "second";
  }
});

async function runcode(run?: boolean) {
  _runcode();

  if (!context.value || context.value?.length < 20) {
    ElMessage.error("代码内容太少");
    return;
  }

  if (!run && !textarea.value) {
    ElMessage.error("请填入测试用例");
    drawer.value = true;
    return;
  }

  runTestLoading.value = true;
  drawer.value = true;
  const scoket: Socket | undefined =
    store.state.socket;
  if (!question.value.ID) return;
  const arr: [string, any][] = [];

  arr[0] = ["_method_", "runcode"];
  arr[1] = ["type", "scoket"];
  arr[2] = ["questionid", String(question.value.ID)];
  arr[3] = ["questionname", String(question.value.name)];
  arr[4] = ["ismatch", true];
  arr[5] = ["matchid", match.value?.ID];
  arr[6] = ["matchname", match.value?.name];
  jilurizhi(arr);
  scoket.emit("runcode", {
    context: context.value,
    language: language.value,
    textarea: textarea.value,
    questionid: question.value.ID,
    userid: getuser.value.ID,
    run,
    gccoptimize: gccoptimize.value ? '-O2' : undefined,
    // 比赛的运行测试和提交代码 需要加上是否文件读写
    isfile: match.value.isfile || false,
  });
}

// 提交试卷
function mySubmit(b: boolean) {
  loading.value = true;
  setTimeout(() => {
    submit.value(b)
    loading.value = false;
  }, 300);
}

// 有问题？？？？？？
function change(v?: string, e?: monaco.editor.IModelContentChangedEvent) {
  if (e && v) {
    context.value = v;
  }
}

defineExpose({
  context,
  language,
  gccoptimize,
})

const isCf = computed(() => {
  return prop.question.range === 'codeforces'
})

// .zrUp margin-top: 20px;  margin-right: 20px;
let limitDis = 20
// 纵向拖拽自适应宽度
const zrUp = ref<HTMLDivElement>()
const monacoEl = ref<HTMLDivElement>()
const { top, right: monacoElRight, bottom } = useElementBounding(monacoEl)
const { y } = useMouse()
const mousePressed = useMousePressed({ target: zrUp })
// 用来存储拖拽后的高度
const draggedHeight = ref('75%')
// 初始化变量
let initialMouseOffset = 0 // 鼠标点击时到 monaco-container 顶部的偏移量
// 临界值与收缩高度
const minHeightForConsole = 100;
const collapsedHeightForConsole = 40;
const windowHeight = ref(window.innerHeight);
// 是否启用平滑过渡
const isTransitionEnabled = ref(false);
// 鼠标距离底部 当前鼠标 y 位置到窗口底部的距离
const mouseBottomDistance = computed(() => {
  return windowHeight.value - y.value;
});
// 动态计算 ConsoleQuestion 的高度
const consoleHeight = computed(() => {
  if (mousePressed.pressed.value) {
    // 拖拽中，关闭过渡效果
    isTransitionEnabled.value = false;
    // 拖拽时动态计算高度
    const distance = mouseBottomDistance.value;
    return distance < minHeightForConsole
      ? `${collapsedHeightForConsole}px`
      : `${distance}px`;
  } else {
    // 拖拽结束后，启用过渡效果
    isTransitionEnabled.value = true;
    // 非拖拽时返回拖拽结束后的高度
    return `${draggedHeight.value}px`;
  }
});

// 计算编辑器高度
const monacoHeight = computed(() => {
  if (!isCf.value && mousePressed.pressed.value) {
    const newHeight = y.value - top.value - initialMouseOffset
    return newHeight > 0 ? `${newHeight}px` : '0px'
  } else {
    // draggedHeight 会根据 watch(y.value) 来更新
    return isCf.value ? '100%' : draggedHeight.value
  }
})
// 监控 y 轴变化来实时更新拖拽后的高度
watch([y, mousePressed.pressed], ([newY, pressed]) => {
  if (!isCf.value && pressed) {
    const newHeight = newY - top.value - initialMouseOffset
    draggedHeight.value = newHeight > 0 ? `${newHeight}px` : '0px'
  }
})

// 横向拖拽自适应宽度
const asidewidth = ref('46vw')
const zrleft = ref<HTMLDivElement>()
const aside = ref<HTMLDivElement>()
const { left, } = useElementBounding(aside)
const { x } = useMouse()
const { pressed } = useMousePressed({ target: zrleft, touch: false })
watch(() => x.value, e => {
  e = e > (monacoElRight.value - limitDis) ? (monacoElRight.value - limitDis) : e
  if (pressed.value) {
    // margin-right: 20px;
    let w = (e - left.value - limitDis / 2)
    w = w > 0 ? w : limitDis
    asidewidth.value = w + 'px'
    console.log("watch x", asidewidth.value)
  }
})

</script>
<style scoped>
#question {
  height: 100%;
  padding: 0 3% 0;
  /* 外边距 */
  --container-margin: 20px;
  --container-header-height: 20vh;
  --container-bg-color: #fff;
  --monaco-header: 60px;

  overflow: hidden;
}

#question.btn-outline-primary:hover {
  background-color: #409eff;
}

/* 左侧tabs的内容 */
.container-content {
  overflow-y: auto;
  overflow-x: hidden;
  background-color: var(--container-bg-color);
  margin-right: calc(var(--container-margin) * 0.75);
  position: relative;
  padding: 0;
  min-width: var(--container-margin);
}

/* 左侧tabs的内容 */
.container-content-item {
  padding: 2px;
  /* nav-header height:100px margin:var(--container-margin)*/
  height: calc(100vh - 100px - var(--container-margin)*2);
}

/* 右侧分为上下 */
.container-right-box {
  /*  - var(--container-margin)*2 */
  height: calc(100vh - 100px - var(--container-margin)*2);
  min-width: var(--container-margin);
}

.submission-container-right {
  /*  - var(--container-margin)*2 */
  height: calc(100vh - 100px - var(--container-margin)*2);
  background-color: #fff;
  border-radius: var(--container-border-radius);
  box-shadow: var(--container-box-shadow);
}

/* 右侧上 */
.monaco-container-box {
  height: 100%;
  display: flex;
  flex-direction: column;

  overflow: hidden;
}

.monaco-container {
  background: var(--container-bg-color);
  height: 70%;
  min-height: var(--monaco-header);
}

.monaco-header {
  height: var(--monaco-header);
  padding: 10px;
  width: 100%;
  display: flex;
  justify-content: space-between;
  align-items: center;
}

#monaco {
  /* header height 62px */
  height: calc(100% - 62px - var(--container-border-radius));
  overflow: hidden;
}

.headers {
  /* overflow: hidden;
  line-height: 45px; */
  display: flex;
  align-items: center;
  flex-wrap: wrap;
}

.code-submit-btn {
  width: 124px;
  height: 42px;
  border-radius: 8px;
  background-color: rgba(70, 131, 250, 1);
}

/*  */
.console-question {
  border-top: 1px solid #dcdfe6;
  overflow: hidden;
  /* 默认无平滑过渡 */
  transition: none;
}

/* 拖拽结束后启用平滑过渡 */
.console-question.transition-enabled {
  transition: height 1s ease;
}
</style>

<style>
#question .el-tabs__header,
#question .el-tabs--border-card>.el-tabs__content {
  padding: 0;
}

.drawer .el-tabs__content {
  margin: 5px;
  overflow-y: auto;
}

#question button:focus {
  outline: none;
}

#question {
  /* flex-shrink: inherit */
}

/* #question .el-tabs__header,
#question .el-tabs--border-card>.el-tabs__content {
  padding: 0;
}

.Drawer .el-tabs__content {
  margin: 5px;
  overflow-y: auto;
}

#question button:focus {
  outline: none;
} */

/* #question {
  flex-shrink: inherit
} */
</style>